package com.micro.common.util;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * <h1>Jackson工具类</h1>
 * @author LevelCoder
 * @version V1.0.0
 * @email LevelCoder@126.com
 * @date 2020/5/8
 */
public class JacksonUtil {

    private JacksonUtil(){}

    private static ObjectMapper objectMapper = null;
    private static final Logger LOGGER = Logger.getLogger(JacksonUtil.class.getName());

    static{
        if (objectMapper == null){
            objectMapper = new ObjectMapper();
            objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);//默认为false,json标准中feild是带双引号的，这里配置强制要求
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);//默认为true,json中存在javabean中不存在的field时抛出异常，设为false，不抛异常
            objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);//默认为false(不允许),是否允许单引号来包住属性名称和字符串值
        }
    }

    public static ObjectMapper getObjectMapper(){
        return objectMapper;
    }

    public static String toJson(Object object){
        try {
            return objectMapper.writeValueAsString(object);
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, "jackson tojson error", e);
        }
        return null;
    }

    public static <T> T getObject(String json,Class<T> clazz){
        T objcet = null;
        try {
            objcet = objectMapper.readValue(json, clazz);
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, "jackson getObject error, json:{0}, error:{1}", new Object[]{json, e});
        }
        return objcet;
    }

    public static <T> T getObject(String json,JavaType type){
        T objcet = null;
        try {
            objcet = objectMapper.readValue(json, type);
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, "jackson getObject error, json:{0}, error:{1}", new Object[]{json, e});
        }
        return objcet;
    }

    public static <T> List<T> getList(String json, Class<T> clazz){
        List<T> list = null;
        try {
            list = objectMapper.readValue(json, TypeFactory.defaultInstance().constructCollectionType(List.class, clazz));//clazz
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, "jackson getList error, json:{0}, error:{1}", new Object[]{json, e});
        }
        return list;
    }

    public static <T> List<T> getList(String json,JavaType type){
        List<T> list = null;
        try {
            list = objectMapper.readValue(json, TypeFactory.defaultInstance().constructCollectionType(List.class, type));//JavaType
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, "jackson getList error, json:{0}, error:{1}", new Object[]{json, e});
        }
        return list;
    }

    public static List<Map<String,String>> getListMap(String json){
        List<Map<String,String>> list = null;
        try {
            list = objectMapper.readValue(json, TypeFactory.defaultInstance().constructCollectionType(List.class, Map.class));//clazz
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, "jackson getList error, json:{0}, error:{1}", new Object[]{json, e});
        }
        return list;
    }

    public static <T> Map<String,T> getMap(String json, Class<T> valueClazz){
        HashMap<String,T> map = null;
        try {
            map = objectMapper.readValue(json,TypeFactory.defaultInstance().constructMapType(HashMap.class, String.class, valueClazz));//JavaType
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, "jackson getMap error, json:{0}, error:{1}", new Object[]{json, e});
        }
        return map;
    }

    public static <T> Map<T, T> getMap(String json, Class<T> keyClazz, Class<T> valueClazz) {
        HashMap<T, T> map = null;
        try {
            map = objectMapper.readValue(json, TypeFactory.defaultInstance().constructMapType(HashMap.class, keyClazz, valueClazz));//JavaType
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, "jackson getMap error, json:{0}, error:{1}", new Object[]{json, e});
        }
        return map;
    }

    public static String getMapValue(String json, String key){
        Map<String, String> map = null;
        try {
            map = objectMapper.readValue(json,TypeFactory.defaultInstance().constructMapType(HashMap.class, String.class, String.class));//JavaType
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, "jackson getMapValue error, json:{0}, error:{1}", new Object[]{json, e});
        }
        if(map!=null && map.size()>0){
            return map.get(key);
        }
        return null;
    }

    public JavaType getJavaListType(Class<?> clazz) {
        return TypeFactory.defaultInstance().constructCollectionType(List.class, clazz);
    }

    public JavaType getJavaListType(JavaType type) {
        return TypeFactory.defaultInstance().constructCollectionType(List.class, type);
    }

    public JavaType getJavaMapType(Class<?> keyClass, Class<?> valueClass) {
        return TypeFactory.defaultInstance().constructMapType(HashMap.class, keyClass, valueClass);
    }
}
